package update_quant_account

import (
	"adam2/internal/model"
	"anubis-framework/pkg/io"
	"anubis-framework/pkg/util"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"math/big"
)

// 买入之后更新quant_account
type UpdateQuantAccountAfterBuy struct {
	db *gorm.DB
}

// 初始化
func (u *UpdateQuantAccountAfterBuy) Init(db *gorm.DB) {
	u.db = db
}

// 在买入之后更新quant_account
func (u *UpdateQuantAccountAfterBuy) Exec(transactionDate string) {
	io.Infoln("在买入之后更新quant_account")

	// 返回量化账户
	var quantAccountArray model.QuantAccountArray
	u.db.Table("quant_account").Select("*").Order("id_ asc").Find(&quantAccountArray)

	for _, quantAccount := range quantAccountArray {

		// 股票资产
		var stockAssets float64 = 0
		// 当天买入的股票资产
		var currentBuyOrSellStockAssets float64 = 0
		// 买入股票的数量
		var sellOrBuyStockNumber int = 0

		// 计算每一个量化账户，在某一天买完股票后的收益
		var quantStockTransactRecordArray model.QuantStockTransactRecordArray
		u.db.Raw("select * from quant_stock_transact_record qstr "+
			"where qstr.account_name = ? "+
			"and qstr.sell_date is null and qstr.sell_price is null and qstr.sell_amount is null",
			(*quantAccount).AccountName).Scan(&quantStockTransactRecordArray)

		// 如果没有买股票，则直接将quant_account表中的记录插入到quant_account_log表中
		if quantStockTransactRecordArray == nil || len(quantStockTransactRecordArray) == 0 {
			// 向表quant_account_log中插入数据
			//u.db.Exec("insert into quant_account_log(DATE_, ACCOUNT_NAME, HOLD_STOCK_NUMBER, STOCK_ASSETS, "+
			//	"CAPITAL_ASSETS, TOTAL_ASSETS, TOTAL_STAMP_DUTY, TOTAL_REGISTRATE_FEE_WHEN_BUY, TOTAL_COMMISSION_WHEN_BUY, "+
			//	"TOTAL_REGISTRATE_FEE_WHEN_SELL, TOTAL_COMMISSION_WHEN_SELL) "+
			//	"select to_date(?, 'yyyy-mm-dd'), t.ACCOUNT_NAME, t.HOLD_STOCK_NUMBER, t.STOCK_ASSETS, t.CAPITAL_ASSETS, t.TOTAL_ASSETS, t.TOTAL_STAMP_DUTY, "+
			//	"t.TOTAL_REGISTRATE_FEE_WHEN_BUY, t.TOTAL_COMMISSION_WHEN_BUY, t.TOTAL_REGISTRATE_FEE_WHEN_SELL, t.TOTAL_COMMISSION_WHEN_SELL "+
			//	"from quant_account t where t.account_name = ?",
			//	transactionDate, (*quantAccount).AccountName)

			continue
		}

		for _, quantStockTransactRecord := range quantStockTransactRecordArray {
			// 查找某只股票在某一天的收盘价
			// 股票的收盘价
			var currentClosePrice float64 = -1
			u.db.Raw("select t.close_price from stock_transaction_data_all t "+
				"where t.code_ = ? and t.date_ = to_date(?, 'yyyy-mm-dd')",
				quantStockTransactRecord.StockCode, transactionDate).Scan(&currentClosePrice)

			if currentClosePrice == -1 {
				// 说明股票在这一天没有交易记录
				io.Infoln("股票[%s]在日期[%s]没有交易记录，可能是停牌，开始查找前一个交易日的记录", quantStockTransactRecord.StockCode, transactionDate)

				// 如果在某一天没有收盘价，比如停牌，则查找最近一个交易日的收盘价
				u.db.Raw("select std.close_price from (select * from stock_transaction_data_all t "+
					"where t.code_ = ? and t.date_ < to_date(?, 'yyyy-mm-dd') order by t.date_ desc) std where rownum <= 1",
					quantStockTransactRecord.StockCode, transactionDate).Scan(&currentClosePrice)
			}

			// 买入股票后的收益
			decimalValue := decimal.NewFromFloat(currentClosePrice)
			decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(quantStockTransactRecord.BuyAmount)))
			res, _ := decimalValue.Float64()
			a := new(big.Rat).SetFloat64(stockAssets)
			b := new(big.Rat).SetFloat64(res)
			stockAssets, _ = new(big.Rat).Add(a, b).Float64()
			sellOrBuyStockNumber = sellOrBuyStockNumber + 1

			// 计算当天买入的股票资产
			if util.DateToString(quantStockTransactRecord.BuyDate) == transactionDate {
				decimalValue := decimal.NewFromFloat(currentClosePrice)
				decimalValue = decimalValue.Mul(decimal.NewFromInt(int64(quantStockTransactRecord.BuyAmount)))
				res, _ := decimalValue.Float64()
				a := new(big.Rat).SetFloat64(currentBuyOrSellStockAssets)
				b := new(big.Rat).SetFloat64(res)
				currentBuyOrSellStockAssets, _ = new(big.Rat).Add(a, b).Float64()
			}
		}

		// 更新quant_account表
		var registrationFeeWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.registration_fee_when_buy), 0) from quant_stock_transact_record t1 "+
			"where t1.account_name = ? and t1.sell_price is null and t1.sell_amount is null and t1.sell_date is null "+
			"and t1.buy_date=to_date(?,'yyyy-mm-dd')",
			(*quantAccount).AccountName, transactionDate).Scan(&registrationFeeWhenBuy)
		var commissionWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.commission_when_buy), 0) from quant_stock_transact_record t1 "+
			"where t1.account_name = ? and t1.sell_price is null and t1.sell_amount is null and t1.sell_date is null "+
			"and t1.buy_date=to_date(?,'yyyy-mm-dd')",
			(*quantAccount).AccountName, transactionDate).Scan(&commissionWhenBuy)
		var totalStampDuty float64
		u.db.Raw("select COALESCE(sum(t1.stamp_duty), 0) from quant_stock_transact_record t1 where t1.account_name = ?",
			(*quantAccount).AccountName).Scan(&totalStampDuty)
		var totalRegistrationFeeWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.registration_fee_when_buy), 0) from quant_stock_transact_record t1 where t1.account_name = ?",
			(*quantAccount).AccountName).Scan(&totalRegistrationFeeWhenBuy)
		var totalCommissionWhenBuy float64
		u.db.Raw("select COALESCE(sum(t1.commission_when_buy), 0) from quant_stock_transact_record t1 where t1.account_name = ?",
			(*quantAccount).AccountName).Scan(&totalCommissionWhenBuy)
		u.db.Exec("update quant_account t "+
			"set t.hold_stock_number = ?, t.stock_assets = round(?, 4), "+
			"t.total_assets = round(? + t.capital_assets - ? - ? - ?, 4), "+
			//"t.total_assets = round(t.total_assets - ? - ?, 4), "+
			// 下面这行可能有错，正确的可能是：资金资产=总资产-股票资产，否则资金资产部分可能就会出现负数。
			//"t.capital_assets = round(t.total_assets - ? - ? - ?, 4), "+
			"t.capital_assets = round(t.capital_assets - ? - ? - ?, 4), "+
			//"t.total_stamp_duty = ?,"+
			"t.total_registrate_fee_when_buy = ?,"+
			"t.total_commission_when_buy = ? "+
			//"t.total_registrate_fee_when_sell = ?, "+
			//"t.total_commission_when_sell = ? "+
			"where t.account_name = ?",
			sellOrBuyStockNumber, stockAssets,
			stockAssets, currentBuyOrSellStockAssets, registrationFeeWhenBuy, commissionWhenBuy,
			//stockAssets, registrationFeeWhenBuy, commissionWhenBuy,
			/*stockAssets, registrationFeeWhenBuy, commissionWhenBuy,*/
			currentBuyOrSellStockAssets, registrationFeeWhenBuy, commissionWhenBuy,
			//sumStampDuty,
			totalRegistrationFeeWhenBuy,
			totalCommissionWhenBuy,
			//sumRegistrationFeeWhenSell,
			//sumCommissionWhenSell,
			(*quantAccount).AccountName)

		// 向表quant_account_log中插入数据
		//u.db.Exec("insert into quant_account_log(DATE_, ACCOUNT_NAME, HOLD_STOCK_NUMBER, STOCK_ASSETS, "+
		//	"CAPITAL_ASSETS, TOTAL_ASSETS, TOTAL_STAMP_DUTY, TOTAL_REGISTRATE_FEE_WHEN_BUY, TOTAL_COMMISSION_WHEN_BUY, "+
		//	"TOTAL_REGISTRATE_FEE_WHEN_SELL, TOTAL_COMMISSION_WHEN_SELL) "+
		//	"select to_date(?, 'yyyy-mm-dd'), t.ACCOUNT_NAME, t.HOLD_STOCK_NUMBER, t.STOCK_ASSETS, t.CAPITAL_ASSETS, t.TOTAL_ASSETS, t.TOTAL_STAMP_DUTY, "+
		//	"t.TOTAL_REGISTRATE_FEE_WHEN_BUY, t.TOTAL_COMMISSION_WHEN_BUY, t.TOTAL_REGISTRATE_FEE_WHEN_SELL, t.TOTAL_COMMISSION_WHEN_SELL "+
		//	"from quant_account t where t.account_name = ?",
		//	transactionDate, (*quantAccount).AccountName)
	}
}
